#!/bin/sh /etc/rc.common

. /usr/share/libubox/jshn.sh

USE_PROCD=1
START=60

OUI_HTTPD_BIN="/usr/sbin/oui-httpd"
PX5G_BIN="/usr/sbin/px5g"
OPENSSL_BIN="/usr/bin/openssl"

NO_AUTH_FILE="/var/run/oui-httpd-no-auth.json"

generate_keys() {
	local cfg="$1"
	local key="$2"
	local crt="$3"
	local days bits country state location commonname

	config_get days       "$cfg" days
	config_get bits       "$cfg" bits
	config_get country    "$cfg" country
	config_get state      "$cfg" state
	config_get location   "$cfg" location
	config_get commonname "$cfg" commonname
	config_get key_type   "$cfg" key_type
	config_get ec_curve   "$cfg" ec_curve

	# Prefer px5g for certificate generation (existence evaluated last)
	local GENKEY_CMD=""
	local KEY_OPTS="rsa:${bits:-2048}"
	local UNIQUEID=$(dd if=/dev/urandom bs=1 count=4 | hexdump -e '1/1 "%02x"')
	[ "$key_type" = "ec" ] && KEY_OPTS="ec -pkeyopt ec_paramgen_curve:${ec_curve:-P-256}"
	[ -x "$OPENSSL_BIN" ] && GENKEY_CMD="$OPENSSL_BIN req -x509 -sha256 -nodes"
	[ -x "$PX5G_BIN" ] && GENKEY_CMD="$PX5G_BIN selfsigned"
	[ -n "$GENKEY_CMD" ] && {
		$GENKEY_CMD \
			-days ${days:-730} -newkey ${KEY_OPTS} -keyout "${SSL_KEY}.new" -out "${SSL_CERT}.new" \
			-subj /C="${country:-ZZ}"/ST="${state:-Somewhere}"/L="${location:-Unknown}"/O="${commonname:-OpenWrt}$UNIQUEID"/CN="${commonname:-OpenWrt}"
		sync
		mv "${SSL_KEY}.new" "${SSL_KEY}"
		mv "${SSL_CERT}.new" "${SSL_CERT}"
	}
}

parse_no_auth_methods() {
	local cfg="$1"
	local method

	config_get object "$cfg" object
	config_get methods "$cfg" method

	[ -n "$object" ] || return 0

	if [ $(json_is_a "$object" array) ];
	then
		json_select "$object"
	else
		json_add_array "$object"
	fi

	for method in $methods; do
		json_add_string "" "$method"
	done

	json_select ..
}

start_instance() {
	local cfg="$1"
	local listen http https home index verbose

	procd_open_instance
	procd_set_param command $OUI_HTTPD_BIN

	config_get verbose "$cfg" verbose 0

	while [ $verbose -gt 0 ];
	do
		procd_append_param command -v
		let verbose=verbose-1
	done

	procd_append_param command --rpc /usr/lib/oui-httpd/rpc --db /etc/oui-httpd/oh.db

	config_get http "$cfg" listen_http
	for listen in $http; do
		procd_append_param command -a "$listen"
	done

	config_get https "$cfg" listen_https
	config_get SSL_CERT "$cfg" cert /etc/oui-httpd/ssl.crt
	config_get SSL_KEY  "$cfg" key  /etc/oui-httpd/ssl.key

	[ -n "$https" ] && {
		[ -s "$SSL_CERT" -a -s "$SSL_KEY" ] || {
			config_foreach generate_keys cert
		}

		[ -f "$SSL_CERT" -a -f "$SSL_KEY" ] && {
			procd_append_param command -C "$SSL_CERT"
			procd_append_param command -K "$SSL_KEY"

			for listen in $https; do
				procd_append_param command -s "$listen"
			done
		}
	}

	config_get home "$cfg" home
	config_get index "$cfg" index
	config_get cgi_prefix "$cfg" cgi_prefix

	json_init
	json_load '{}'

	config_foreach parse_no_auth_methods no-auth-methods

	json_dump > "$NO_AUTH_FILE"

	procd_append_param  command --no-auth-file "$NO_AUTH_FILE"

	[ -n "$home" ] && procd_append_param  command --home "$home"
	[ -n "$index" ] && procd_append_param  command --index "$index"
	[ -n "$cgi_prefix" ] && procd_append_param  command -x "$cgi_prefix"

	procd_set_param respawn
	procd_close_instance
}

start_service() {
	config_load oui-httpd
	config_foreach start_instance oui-httpd
}

service_triggers() {
	procd_add_reload_trigger "oui-httpd"
}
